﻿//#define UNMANAGED
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace CoreLib.MySQL
{
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public unsafe struct QuerySegment
    {
#if UNMANAGED
        internal Connector Connector;
        internal Comparisson Comparisson;
        internal char* Column;
        internal char* Value;
#else
        internal Connector Connector;
        internal Comparisson Comparisson;
        internal string Column;
        internal object Value;
#endif

    }
    public unsafe class DbBaseQuery<T> where T : IDbQuery
    {
        protected T TQuery;
#if UNMANAGED
        protected Queue<IntPtr> whereClauses;
        protected Queue<IntPtr> queryClauses;
#else
        protected Queue<QuerySegment> whereClauses;
        protected Queue<QuerySegment> queryClauses;
#endif
        protected SortBy sortType;
        protected int limit = 0;
        protected string table;
        private int counter = 0;
        protected string GetParameter()
        {
            return string.Format("?{0}", counter++);
        }

        internal DbBaseQuery()
        {
#if UNMANAGED
            whereClauses = new Queue<IntPtr>();
            queryClauses = new Queue<IntPtr>();
#else
            whereClauses = new Queue<QuerySegment>();
            queryClauses = new Queue<QuerySegment>();
#endif
        }

        protected T Limit(int _limit)
        {
            this.limit = _limit;
            return TQuery;
        }

        protected T Where(string column, Comparisson comparer, object value)
        {
#if UNMANAGED
            QuerySegment* segment = (QuerySegment*)Marshal.AllocHGlobal(column.Length + 2 + value.ToString().Length);
            segment->Comparisson = comparer;
            segment->Connector = Connector.Where;
            fixed (char* col = column, val = value.ToString())
            {
                segment->Column = col;
                segment->Value = val;
            }
            whereClauses.Enqueue((IntPtr)segment);
            return TQuery;
#else
            QuerySegment segment = new QuerySegment();
            segment.Column = column;
            segment.Comparisson = comparer;
            segment.Connector = Connector.Where;
            segment.Value = value;
            whereClauses.Enqueue(segment);
            return TQuery;
#endif
        }

        protected T And(string column, Comparisson comparer, object value)
        {
#if UNMANAGED
            QuerySegment* segment = (QuerySegment*)Marshal.AllocHGlobal(column.Length + 2 + value.ToString().Length);
            segment->Comparisson = comparer;
            segment->Connector = Connector.And;
            fixed (char* col = column, val = value.ToString())
            {
                segment->Column = col;
                segment->Value = val;
            }
            whereClauses.Enqueue((IntPtr)segment);
            return TQuery;
#else
            QuerySegment segment = new QuerySegment();
            segment.Column = column;
            segment.Comparisson = comparer;
            segment.Connector = Connector.And;
            segment.Value = value;
            whereClauses.Enqueue(segment);
            return TQuery;
#endif
        }

        protected T Or(string column, Comparisson comparer, object value)
        {
#if UNMANAGED
            QuerySegment* segment = (QuerySegment*)Marshal.AllocHGlobal(column.Length + 2 + value.ToString().Length);
            segment->Comparisson = comparer;
            segment->Connector = Connector.Or;
            fixed (char* col = column, val = value.ToString())
            {
                segment->Column = col;
                segment->Value = val;
            }
            whereClauses.Enqueue((IntPtr)segment);
            return TQuery;
#else
            QuerySegment segment = new QuerySegment();
            segment.Column = column;
            segment.Comparisson = comparer;
            segment.Connector = Connector.Or;
            segment.Value = value;
            whereClauses.Enqueue(segment);
            return TQuery;
#endif
        }

        protected T AddParam(string column, object value)
        {
#if UNMANAGED
            QuerySegment* segment = (QuerySegment*)Marshal.AllocHGlobal(column.Length + 2 + value.ToString().Length);
            fixed (char* col = column, val = value.ToString())
            {
                segment->Column = col;
                segment->Value = val;
            }
            queryClauses.Enqueue((IntPtr)segment);
            return TQuery;
#else
            QuerySegment segment = new QuerySegment();
            segment.Column = column;
            segment.Value = value;
            queryClauses.Enqueue(segment);
            return TQuery;
#endif
        }

        public IAsyncResult BeginExecute()
        {
            return BeginExecute(null, null);
        }

        public IAsyncResult BeginExecute(AsyncCallback callback)
        {
            return BeginExecute(callback, null);
        }

        public IAsyncResult BeginExecute(AsyncCallback callback, object @object)
        {
            Action action = TQuery.Execute;
            return action.BeginInvoke(callback, @object);
        }

        protected static string TranslateOperator(Comparisson @operator)
        {
            switch (@operator)
            {
                case Comparisson.DistinctTo:
                    return "<>";
                case Comparisson.EqualTo:
                    return "=";
                case Comparisson.EqualOrGreaterThan:
                    return ">=";
                case Comparisson.EqualOrLesserThan:
                    return "<=";
                case Comparisson.GreaterThan:
                    return ">";
                case Comparisson.LesserThan:
                    return "<";
                default:
                    return "=";
            }
        }
    }
}
